﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bxas.Core.Exceptions;
using System.Data;
using System.IO;
using System.Xml.Serialization;
using System.Reflection;
using System.Data.SqlClient;

namespace Bxas.Core
{
    public class CoreBs
    {
        public ConnectionManager connectionManager;
        public CoreBs()
        {
            connectionManager = new ConnectionManager(System.Configuration.ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString);
        }

        protected String TableName { get; set; }
        protected DataTable DTable = null;

        protected Boolean _update<T>(T updateObject) where T : ColumnInfo, new()
        {
            try
            {
                if (updateObject.IsUpdateOrInsert.Count == 0)
                    return false;

                String sql = "Update " + updateObject.TableName + " SET ";
                PropertyInfo[] Fileds = typeof(T).GetProperties();
                SqlCommand sqlCommand = new SqlCommand();


                object id = null;

                for (int i = 0; i < Fileds.Count(); i++)
                {
                    if (updateObject.IsUpdateOrInsert.Keys.Contains(Fileds[i].Name))
                    {
                        if (Fileds[i].Name != updateObject.priymatyKeyColumnName)
                        {
                            sql += Fileds[i].Name + " = @" + Fileds[i].Name + ",";
                            sqlCommand.Parameters.AddWithValue("@" + Fileds[i].Name, Convert.ChangeType(((PropertyInfo)updateObject.GetFields(typeof(T))[i, 0]).GetValue(updateObject, null), Fileds[i].PropertyType));
                        }
                    }
                    if (Fileds[i].Name == updateObject.priymatyKeyColumnName)
                    {
                        id = ((PropertyInfo)updateObject.GetFields(typeof(T))[i, 0]).GetValue(updateObject, null);
                    }
                }


                sql = sql.Remove(sql.Length - 1, 1);
                sql += " where " + updateObject.priymatyKeyColumnName + "= @Id";

                sqlCommand.Parameters.AddWithValue("@Id", Convert.ChangeType(id, updateObject.priymatyKeyColumnType));

                return connectionManager.execSQL(sql, sqlCommand);
            }
            catch (BxasCoreException ex)
            {

                throw ex;
            }


        }
        protected Boolean _insert<T>(T insertObject) where T : ColumnInfo, new()
        {

            try
            {
                if (insertObject.IsUpdateOrInsert.Count == 0)
                    return false;

                String sql = "insert " + insertObject.TableName + " (";
                String sql1 = "(";
                PropertyInfo[] Fileds = typeof(T).GetProperties();
                SqlCommand sqlCommand = new SqlCommand();

                for (int i = 0; i < Fileds.Count(); i++)
                {
                    if (insertObject.IsUpdateOrInsert.Keys.Contains(Fileds[i].Name))
                    {
                        sql += Fileds[i].Name + ",";
                        sql1 += "@" + Fileds[i].Name + ",";
                        sqlCommand.Parameters.AddWithValue("@" + Fileds[i].Name, Convert.ChangeType(((PropertyInfo)insertObject.GetFields(typeof(T))[i, 0]).GetValue(insertObject, null), Fileds[i].PropertyType));
                    }
                }


                sql = sql.Remove(sql.Length - 1, 1);
                sql1 = sql1.Remove(sql1.Length - 1, 1);
                sql1 += ")";
                sql += ") VALUES " + sql1;

                return connectionManager.execSQL(sql, sqlCommand);
            }
            catch (Exception ex)
            {

                throw ex;
            }




        }
        protected Boolean _delete<T>(T deletedObject) where T : ColumnInfo, new()
        {
            try
            {
                String sql = "Delete From " + deletedObject.TableName + " WHERE " + deletedObject.priymatyKeyColumnName + " = @" + deletedObject.priymatyKeyColumnName;
                PropertyInfo[] Fileds = typeof(T).GetProperties();
                SqlCommand sqlCommand = new SqlCommand();

                for (int i = 0; i < Fileds.Count(); i++)
                {
                    if (Fileds[i].Name == deletedObject.priymatyKeyColumnName)
                    {
                        sqlCommand.Parameters.AddWithValue("@" + Fileds[i].Name, Convert.ChangeType(((PropertyInfo)deletedObject.GetFields(typeof(T))[i, 0]).GetValue(deletedObject, null), Fileds[i].PropertyType));
                    }
                }


                return connectionManager.execSQL(sql, sqlCommand); ;
            }
            catch (BxasCoreException ex)
            {
                if (((SqlException)ex.InnerException).ErrorCode == 547)
                {
                    return is_deleted_true<T>(deletedObject);
                }
                throw ex;
            }

        }
        private Boolean is_deleted_true<T>(T updateObject) where T : ColumnInfo, new()
        {
            try
            {
                if (updateObject.IsUpdateOrInsert.Count == 0)
                    return false;

                String sql = "Update " + updateObject.TableName + " SET IsDeleted=True ";
                PropertyInfo[] Fileds = typeof(T).GetProperties();
                SqlCommand sqlCommand = new SqlCommand();


                object id = null;

                for (int i = 0; i < Fileds.Count(); i++)
                {
                    if (Fileds[i].Name == updateObject.priymatyKeyColumnName)
                    {
                        id = ((PropertyInfo)updateObject.GetFields(typeof(T))[i, 0]).GetValue(updateObject, null);
                    }
                }

                sql += " where " + updateObject.priymatyKeyColumnName + "= @Id";

                sqlCommand.Parameters.AddWithValue("@Id", Convert.ChangeType(id, updateObject.priymatyKeyColumnType));

                return connectionManager.execSQL(sql, sqlCommand);
            }
            catch (BxasCoreException ex)
            {
                throw ex;
            }


        }
        protected List<T> _get<T>(string sql) where T : ColumnInfo, new()
        {
            try
            {
                DTable = new DataTable();
                connectionManager.getData(ref DTable, sql, null);
                return ToList<T>(DTable);
            }
            catch (BxasCoreException ex)
            {
                throw ex;
            }
        }
        protected List<T> _get<T>(SqlCommand sqlcommand) where T : ColumnInfo, new()
        {
            try
            {
                DTable = new DataTable();
                connectionManager.getData(ref DTable, sqlcommand);
                return ToList<T>(DTable);
            }
            catch (BxasCoreException ex)
            {

                throw ex;
            }


        }
        protected List<T> _get_all<T>(List<String> ColumnNames) where T : ColumnInfo, new()
        {
            try
            {
                PropertyInfo[] Fileds = typeof(T).GetProperties();
                String sql = "";

                sql = set_select_sql_columns(ColumnNames, sql);

                sql += " From " + (new T()).TableName;

                foreach (var item in Fileds)
                {
                    if (item.Name == "IsDeleted")
                    {
                        sql += " where IsDeleted=0";
                        break;
                    }
                }


                DTable = new DataTable();
                connectionManager.getData(ref DTable, sql, null);
                return ToList<T>(DTable);
            }
            catch (BxasCoreException ex)
            {
                throw ex;
            }

        }
        protected List<T> _get_all_with_all_columns<T>() where T : ColumnInfo, new()
        {
            try
            {
                return _get_all<T>(null);
            }
            catch (BxasCoreException ex)
            {
                throw ex;
            }
        }
        protected T _get_by_primarykey<T>(object pk, List<String> ColumnNames) where T : ColumnInfo, new()
        {
            try
            {
                T t = new T();

                PropertyInfo[] Fileds = typeof(T).GetProperties();
                SqlCommand sqlCommand = new SqlCommand();
                String sql = " Select ";

                sql = set_select_sql_columns(ColumnNames, sql);

                sql += " From " + (new T()).TableName;

                sql += " where " + t.priymatyKeyColumnName + " = @" + t.priymatyKeyColumnName;

                foreach (var item in Fileds)
                {
                    if (item.Name == "IsDeleted")
                    {
                        sql += " and IsDeleted=0";
                        break;
                    }
                }
                sqlCommand.CommandText = sql;
                sqlCommand.Parameters.AddWithValue("@" + t.priymatyKeyColumnName, Convert.ChangeType(pk, t.priymatyKeyColumnType));


                DTable = new DataTable();
                connectionManager.getData(ref DTable, sqlCommand);
                return t;
            }
            catch (BxasCoreException ex)
            {
                throw ex;
            }

        }
        private static String set_select_sql_columns(List<String> ColumnNames, String sql)
        {
            sql = " Select ";
            if (ColumnNames != null)
            {
                if (ColumnNames.Count > 0)
                {
                    for (int i = 0; i < ColumnNames.Count; i++)
                    {
                        if (i != ColumnNames.Count - 1)
                            sql += ColumnNames[i].ToString() + ", ";
                        else
                            sql += ColumnNames[i].ToString();

                    }
                }
                else
                    sql += "* ";
            }
            else
                sql += "* ";
            return sql;
        }
        private static object[,] outputFields = null;
        protected static List<T> ToList<T>(DataTable dt) where T : ColumnInfo, new()
        {
            List<T> recordList = new List<T>();
            outputFields = null;
            #region Generated Code
            T record = null;
            DataTable table = null;

            try
            {

                table = dt;

                if (table == null)
                {
                    return null;
                }

                if (table.Rows.Count < 1)
                {
                    return null;
                }

                if (outputFields == null)
                {
                    record = new T();
                    outputFields = record.GetFields(typeof(T));
                }

                for (int i = 0; i < table.Rows.Count; i++)
                {
                    record = new T();
                    record.SetFields(outputFields, table.Rows[i]);
                    record.IsDirty = false;
                    recordList.Add(record);
                }
            }
            catch (Exception) { recordList = null; throw; }
            #endregion

            return recordList;
        }
        protected bool IsDataTableNull() { return DTable == null; }


        #region ToXml / FromXml

        virtual protected string Serialize()
        {
            if (IsDataTableNull()) throw new Exception("Kayıt yok");

            DataSet dataSet = new DataSet();
            dataSet.Tables.Add(DTable);
            StringWriter writer = new StringWriter();
            XmlSerializer ser = new XmlSerializer(typeof(DataSet));
            ser.Serialize(writer, dataSet);
            dataSet.Tables.Clear();
            return writer.ToString();
        }
        virtual protected void Deserialize(string xml)
        {
            DataSet dataSet = new DataSet();
            StringReader reader = new StringReader(xml);
            XmlSerializer ser = new XmlSerializer(typeof(DataSet));
            dataSet = (DataSet)ser.Deserialize(reader);
            DTable = new DataTable();
            this.DTable = dataSet.Tables[0];
            dataSet.Tables.Clear();
        }
        virtual protected string ToXml()
        {
            if (IsDataTableNull()) throw new Exception("Kayıt yok");

            DataSet dataSet = new DataSet();
            dataSet.Tables.Add(DTable);
            StringWriter writer = new StringWriter();
            dataSet.WriteXml(writer);
            dataSet.Tables.Clear();
            return writer.ToString();
        }
        virtual protected string ToXml(XmlWriteMode mode)
        {
            if (IsDataTableNull()) throw new Exception("Kayıt yok");

            DataSet dataSet = new DataSet();
            dataSet.Tables.Add(DTable);
            StringWriter writer = new StringWriter();
            dataSet.WriteXml(writer, mode);
            dataSet.Tables.Clear();
            return writer.ToString();
        }
        virtual protected void FromXml(string xml)
        {
            DataSet dataSet = new DataSet();
            StringReader reader = new StringReader(xml);
            dataSet.ReadXml(reader);
            DTable = new DataTable();
            this.DTable = dataSet.Tables[0];
            dataSet.Tables.Clear();
        }
        virtual protected void FromXml(string xml, XmlReadMode mode)
        {
            DataSet dataSet = new DataSet();
            StringReader reader = new StringReader(xml);
            dataSet.ReadXml(reader, mode);
            DTable = new DataTable();
            this.DTable = dataSet.Tables[0];
            dataSet.Tables.Clear();
        }

        #endregion
    }
}
